package com.duckclouddrive.component;

import com.duckclouddrive.entity.constants.Constants;
import com.duckclouddrive.entity.dto.DownloadFileDto;
import com.duckclouddrive.entity.dto.SysSettingsDto;
import com.duckclouddrive.entity.dto.UserSpaceDto;
import com.duckclouddrive.entity.po.UserInfo;
import com.duckclouddrive.entity.query.FileInfoQuery;
import com.duckclouddrive.entity.query.UserInfoQuery;
import com.duckclouddrive.mappers.FileInfoMapper;
import com.duckclouddrive.mappers.UserInfoMapper;
import org.apache.tomcat.jni.FileInfo;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component("redisComponent")
public class RedisComponent {

    @Resource
    private RedisUtils redisUtils;

    @Resource
    private UserInfoMapper<UserInfo, UserInfoQuery> userInfoMapper;

    @Resource
    private FileInfoMapper<FileInfo, FileInfoQuery> fileInfoMapper;

    /**
     * 获取系统设置
     *
     * @return
     */
    public SysSettingsDto getSysSettingsDto() {
        SysSettingsDto sysSettingsDto = (SysSettingsDto) redisUtils.get(Constants.REDIS_KEY_SYS_SETTING);
        if (sysSettingsDto == null) {
            sysSettingsDto = new SysSettingsDto();
            redisUtils.set(Constants.REDIS_KEY_SYS_SETTING, sysSettingsDto);
        }
        return sysSettingsDto;
    }


    /**
     * 保存系统设置到Redis
     *
     * @param sysSettingsDto 系统设置数据传输对象，包含要保存的系统设置信息
     */
    public void saveSysSettingsDto(SysSettingsDto sysSettingsDto) {
        redisUtils.set(Constants.REDIS_KEY_SYS_SETTING, sysSettingsDto);
    }
    public void saveDownloadCode(String code, DownloadFileDto downloadFileDto) {
        redisUtils.setex(Constants.REDIS_KEY_DOWNLOAD + code, downloadFileDto, Constants.REDIS_KEY_EXPIRES_FIVE_MIN);
    }

    public DownloadFileDto getDownloadCode(String code) {
        return (DownloadFileDto) redisUtils.get(Constants.REDIS_KEY_DOWNLOAD + code);
    }
    /**
     * 获取用户的空间使用情况
     * 首先尝试从Redis缓存中获取用户的空间使用信息如果用户的信息不存在，则计算并设置用户的空间使用情况和总空间大小，
     * 并将这些信息存储回Redis缓存中
     *
     * @param userId 用户ID
     * @return 返回用户的空间使用情况对象
     */
    public UserSpaceDto getUserSpaceUse(String userId) {
        // 从Redis缓存中获取用户的空间使用情况
        UserSpaceDto spaceDto = (UserSpaceDto) redisUtils.get(Constants.REDIS_KEY_USER_SPACE_USE + userId);
        if (null == spaceDto) {
            // 如果用户的空间使用信息不存在，则创建一个新的UserSpaceDto对象
            spaceDto = new UserSpaceDto();
            //查询当前用户已经上传文件大小总和
            Long useSpace = this.fileInfoMapper.selectUseSpace(userId);
            // 设置用户已使用空间为0
            spaceDto.setUseSpace(useSpace);
            // 设置用户的总空间大小（初始化为系统设置的用户初始使用空间大小）
            spaceDto.setTotalSpace(getSysSettingsDto().getUserInitUseSpace() * Constants.MB);
            // 将用户的空间使用信息存储回Redis缓存中，并设置过期时间
            redisUtils.setex(Constants.REDIS_KEY_USER_SPACE_USE + userId, spaceDto, Constants.REDIS_KEY_EXPIRES_DAY);
        }
        // 返回用户的空间使用情况
        return spaceDto;
    }
    /**
     * 保存已使用的空间
     *
     * @param userId
     */
    public void saveUserSpaceUse(String userId, UserSpaceDto userSpaceDto) {
        redisUtils.setex(Constants.REDIS_KEY_USER_SPACE_USE + userId, userSpaceDto, Constants.REDIS_KEY_EXPIRES_DAY);
    }

    /**
     * 重置用户空间使用情况
     *
     * 本方法用于更新用户的存储空间使用信息，并缓存该信息以提高访问效率
     * 首先，根据用户ID查询该用户已使用的存储空间大小，然后获取用户的总存储空间大小
     * 最后，将这些信息封装到UserSpaceDto对象中，并将其缓存到Redis中
     *
     * @param userId 用户ID，用于查询用户存储空间信息
     * @return 返回包含用户存储空间使用情况的UserSpaceDto对象
     */
    public UserSpaceDto resetUserSpaceUse(String userId) {
        // 创建UserSpaceDto对象，用于存储用户空间使用信息
        UserSpaceDto spaceDto = new UserSpaceDto();

        // 查询用户已使用的存储空间大小，并设置到spaceDto对象中
        Long useSpace = this.fileInfoMapper.selectUseSpace(userId);
        spaceDto.setUseSpace(useSpace);

        // 查询用户信息，包括总存储空间大小，并设置到spaceDto对象中
        UserInfo userInfo = this.userInfoMapper.selectByUserId(userId);
        spaceDto.setTotalSpace(userInfo.getTotalSpace());

        // 将用户空间使用信息缓存到Redis中，以提高后续查询效率
        redisUtils.setex(Constants.REDIS_KEY_USER_SPACE_USE + userId, spaceDto, Constants.REDIS_KEY_EXPIRES_DAY);

        // 返回包含用户空间使用信息的UserSpaceDto对象
        return spaceDto;
    }

    //保存文件临时大小
    public void saveFileTempSize(String userId, String fileId, Long fileSize) {
        Long currentSize = getFileTempSize(userId, fileId);
        redisUtils.setex(Constants.REDIS_KEY_USER_FILE_TEMP_SIZE + userId + fileId, currentSize + fileSize, Constants.REDIS_KEY_EXPIRES_ONE_HOUR);
    }

    /**
     * 获取用户临时文件的大小
     *
     * 本方法通过查询Redis中的特定键值来获取指定用户和文件的临时大小信息临时文件大小信息对于诸如上传过程中断点续传等场景非常重要
     * 它可以帮助应用确定已经上传的数据量，从而避免重复上传和网络资源的浪费
     *
     * @param userId 用户ID，用于标识特定用户的临时文件大小信息
     * @param fileId 文件ID，与特定的文件相关联，用于区分不同的文件
     * @return 当前指定用户和文件的临时大小，如果信息不存在或发生错误，则可能返回null
     */
    public Long getFileTempSize(String userId, String fileId) {
        // 根据用户ID和文件ID拼接的键名，从Redis中获取对应的临时文件大小
        Long currentSize = getFileSizeFromRedis(Constants.REDIS_KEY_USER_FILE_TEMP_SIZE + userId + fileId);
        return currentSize;
    }

    /**
     * 从Redis中获取文件大小
     *
     * @param key Redis中存储的文件大小对应的键
     * @return 文件的大小，如果找不到或转换失败则返回0L
     */
    private Long getFileSizeFromRedis(String key) {
        // 从Redis获取文件大小对象
        Object sizeObj = redisUtils.get(key);

        // 检查获取的对象是否为空
        if (sizeObj == null) {
            return 0L;
        }

        // 尝试将对象转换为Integer类型，并转换为long返回
        if (sizeObj instanceof Integer) {
            return ((Integer) sizeObj).longValue();
        } else if (sizeObj instanceof Long) {
            // 如果对象已经是Long类型，则直接返回
            return (Long) sizeObj;
        }

        // 如果对象既不是Integer也不是Long，则返回默认值0L
        return 0L;
    }
}
